"""
    Really big contoller which contains many mass actions for students in groups editing.
"""

from decimal import Decimal
from datetime import date, timedelta
import turbogears
import cherrypy
from turbogears import widgets, expose, validate, redirect, error_handler
from turbogears import identity, validators

from mnemoply import model
from mnemoply.model import payment, constants
from mnemoply.model.auth import AuthUserOffice, AuthUserFaculty, AuthUserOrg
from mnemoply.model.agreement import Contract, StudentAgreement
from mnemoply.utils import objs2ids, ExceptionsBunch, MigrationException, copyInstance, str2date2, isint, ids2objs
from mnemoply.mass_actions import MassAction, MassActionForm

from mnemoply.preorders import preorders
from mnemoply.controllers import Report
from mnemoply.controllers.containers import ModelObjectContainer
from mnemoply.controllers.lookup import LookupController, TableCol, TableLookupDataSource
from mnemoply.widgets import DictionaryField, YearField, PlanTopicField, \
    MonthField, DiscontField, EmptyValidator, column_widget, \
    TextWithHelperField, EmptyValidator, DecimalValidator, GridField, Span, \
    column_avg_mark, column_possible_day, TemporaryPaymentField, FinalTopicField, \
    GroupField, createGroupField, CouponActiveField, ProjectDefenceField
from mnemoply.error_handling import handle_std_exceptions
from mnemoply.utils import getGroups, ifReferFromGroup, getGroupFromRefer, date2str, planSortFunction

class MACreateProjectDefence(MassAction):
    target_class = model.StudentInGroup
    name = "create_defence"
    title = _("Create defence")
    form = MassActionForm(name=name,
        fields=[
                ProjectDefenceField(
                    name="defence_id",
                    year = constants.getAcademicYear(),
                    label=_("Project defence"),
                ),
            ]
    )

    def call(self, objs, defence_id):
        defence = model.ProjectDefence.get(int(defence_id))

        id_list = []
        for sig in objs:
            if not model.IndividualProjectDefence.selectBy(
                student=sig.student, defence=defence).count():
                id_list.append(
                    model.IndividualProjectDefence(student=sig.student,
                                                   defence=defence,
                                                   startTime=defence.startTime))
            else:
                self.successfully_execute = False
        defence.calculateTimetable(id_list)

class ExtraFieldsSchema(turbogears.validators.Schema):
    filter_extra_fields = False
    allow_extra_fields = True

class MACreateCertificateDelivery(MassAction):
    target_class = model.StudentInGroup
    name = "create_certificate_delivery"
    title = _("Create certificate delivery")

    form = MassActionForm(name=name,
        fields=[
            DictionaryField(
                name="certificate_id",
                model_object_name='Certificate',
                not_empty=True,
                label=_("Certificate"),
            ),
            widgets.CheckBox(name="take_in", label=_("Take in?")),
        ]
    )

    def call(self, sigs, certificate_id, take_in):
        certificate = model.Certificate.get(int(certificate_id))
        for sig in sigs:
            model.CertificateDelivery(student=sig.student, certificate=certificate, takeIn=take_in)

class MACreateChargeRecordForShortCourseWithMonthAndYear(MassAction):
    target_class = model.StudentInGroup
    name = "create_charge_record_for_short_course_with_my"
    title = _("Create charge record for short course with month and year")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )

    def call(self, objs, year, month):
        for sig in objs:
            if model.ChargeRecord.createRecordForShortCourse(sig, year, month) is None:
                self.successfully_execute = False

class MACreateChargeRecordForShortCourse(MassAction):
    target_class = model.StudentInGroup
    name = "create_charge_record_for_short_course"
    title = _("Create charge record for short course")

    def call(self, objs):
        for sig in objs:
            if model.ChargeRecord.createRecordForShortCourse(sig) is None:
                self.successfully_execute = False

class MACharge(MassAction):
    target_class = model.StudentInGroup
    name = "charge_payment"
    title = _("Charge payment")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )

    def call(self, sigs, month, year, can_recharge='0'):
        # XXX workaround for what?
        try:
            can_recharge = bool(int(cherrypy.request.paramMap.get('can_recharge', '0')))
        except:
            can_recharge = False

        try:
            records = payment.charge(sigs, month, year, can_recharge)
        except payment.NeedRechargeError, ex:
            return dict(
                tg_template="genshi:mnemoply.templates.recharge",
                recharge_list=ex.recharge_list,
                ids=objs2ids(sigs),
                month=month,
                year=year,
                action=self.url,
            )

        return dict(
            tg_template="genshi:mnemoply.templates.charge",
            records=records,
            month=month,
            year=year,
            sigs=sigs,
        )

class MAGroupDischarge(MassAction):
    target_class = model.StudentInGroup
    name = "group_discharge"
    title = _("Group discharge")

    form = MassActionForm(name=name,
        fields=[
            DictionaryField(
                name="preorder_id",
                model_object_name='Preorder',
                empty_caption=_("*New preorder*"),
                records=lambda: model.Preorder.selectByPTypeTag('GroupDischarge'),
                label=_("Preorder"),
            ),
            TextWithHelperField(
                name="reason",
                not_empty=True,
                label=_("Reason"),
                records=lambda: [x.name for x in model.DischargeReason.select().orderBy('name')],
                validator=EmptyValidator(not_empty=True),
            ),
            column_widget(model.Transfer.sqlmeta.columns.get('comment')),
            widgets.CheckBox(name="is_self_wish", default=False, label=_("Is self wish?")),
            widgets.CheckBox(name="planned", default=False, label=_("Planned?")),
        ]
    )

    @identity.require(identity.has_any_permission('dba', 'Order:GroupDischarge'))
    def call(self, objs, preorder_id, reason, comment, is_self_wish, planned):
        preorder = preorders.create_or_get(preorder_id, 'GroupDischarge')

        for sig in objs:
            preorder.add(
                student=sig.student, group=sig.group,
                reason=reason, comment=comment,
                isSelfWish=is_self_wish, planned=planned
            )

        raise redirect("/Preorder/%d/" % preorder.obj.id)

class MAGroupTransfer(MassAction):
    target_class = model.StudentInGroup
    name = "group_transfer"
    title = _("Group transfer")

    form = MassActionForm(name=name,
        fields=[
            DictionaryField(
                name="preorder_id",
                model_object_name='Preorder',
                empty_caption=_("*New preorder*"),
                records=lambda: model.Preorder.selectByPTypeTag('GroupTransfer'),
                label=_("Preorder"),
            ),
            GroupField(
                name="group_id",
                not_empty=True,
                label="In group",
            ),
            column_widget(model.Transfer.sqlmeta.columns.get('comment')),
        ]
    )

    @identity.require(identity.has_any_permission('dba', 'Order:GroupTransfer'))
    def call(self, objs, preorder_id, group_id, comment):
        group = model.Group.get(int(group_id))

        preorder = preorders.create_or_get(preorder_id, 'GroupTransfer')

        for sig in objs:
            preorder.add(
                student=sig.student,
                group_from=sig.group, group_to=group,
                comment=comment
            )

        raise redirect("/Preorder/%d/" % preorder.obj.id)

# it temporary workaround for group creation in september
# class MAGroupTransferWithoutOrder(MassAction):
#     target_class = model.StudentInGroup
#     name = "group_transfer_without_order"
#     title = _("Switch group")

#     form = MassActionForm(name=name,
#         fields=[
#             createGroupField(date.today().year),
#         ]
#     )

#     def call(self, objs, group_id):
#         group = model.Group.get(int(group_id))

#         for sig in objs:
#             sig.group = group

#         raise redirect("/StudentInGroup")

class MAPutGrades(MassAction):
    target_class = model.StudentInGroup
    name = "putgrades"
    title = _("Put grades for test")

    common_fields = [
        DictionaryField(name='test_name_id',
            model_object_name='TestName', not_empty=True, label=_("Test name")),
        widgets.CheckBox(name='can_replace',
            default=False, label=_("Replace values?")),
        column_widget(model.Mark.sqlmeta.columns.get('comment')),
        widgets.HiddenField(name='came_from')
    ]

    common_form = widgets.TableForm(fields=common_fields, validator=ExtraFieldsSchema())

    def call(self, objs):
        came_from = cherrypy.request.headerMap['Referer']

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(widgets.TextField(
                name="gr_%d" % sig.id,
                not_empty=False,
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putgrades'),
            submit_text=_("Put grades for test"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_grades_for_test",
            form=form,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    @validate(form=common_form)
    @expose()
    def putgrades(self, obj, came_from, test_name_id,
                  can_replace=False, comment='', **kw):
        # Extract args
        test_name = model.TestName.get(int(test_name_id))

        grades = []
        for k, v in kw.iteritems():
            if not v:
                continue

            assert k[:3] == 'gr_'
            id = int(k[3:])
            if isint(v):
                grades.append((model.StudentInGroup.get(id), int(v)))

        # Put grades
        exceptions = []
        for sig, grade in grades:
            tests = model.TestDelivery.selectBy(test=test_name, student=sig.student)
            if tests.count() > 0:
                test = list(tests)[0]
                if test.grade == grade:
                    continue

                if can_replace:
                    test.grade = grade
                else:
                    exceptions.append((sig.title,
                        _("Test '%s' was pass already") % test_name.title))
            else:
                model.TestDelivery(test=test_name, student=sig.student,
                    grade=grade)

        if len(exceptions) > 0:
            raise ExceptionsBunch(exceptions)

        raise redirect(came_from)

class MAPutGradesForTeacher(MAPutGrades):
    name = "putgrades_for_teacher"
    title = _("Put grades for teacher")

    common_form = MAPutGrades.common_form

    def call(self, objs):
        came_from = cherrypy.request.headerMap['Referer']

        if not ifReferFromGroup(came_from):
            turbogears.flash(_('This mass action works only from group page.'))
            raise turbogears.redirect(came_from)

        number = getGroupFromRefer(came_from)
        user = turbogears.identity.current.user

        if not getGroups(user).count(number):
            turbogears.flash(_('It not your group.'))
            raise turbogears.redirect(came_from)

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(widgets.TextField(
                name="gr_%d" % sig.id,
                not_empty=False,
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putgrades'),
            submit_text=_("Put grades for test"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_grades_for_test",
            form=form,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    @validate(form=common_form)
    @expose()
    def putgrades(self, obj, came_from, test_name_id,
                  can_replace=False, comment='', **kw):
        return MAPutGrades.putgrades(self, obj, came_from, test_name_id, can_replace=can_replace, comment='', **kw)

class MAPutFinalMark(MassAction):
    target_class = model.StudentInGroup
    name = "put_finalmark"
    title = _("Put final mark")

    common_fields = [
        FinalTopicField(name="group_topic_id", not_empty=True, label=_("Topic")),
        widgets.CheckBox(name='can_replace',
            default=False, label=_("Replace values?")),
        widgets.TextField(name="protocol_number", not_empty=False, label=_("Protocol #")),
        column_widget(model.Mark.sqlmeta.columns.get('comment')),
        widgets.HiddenField(name='came_from')
    ]

    common_form = widgets.TableForm(fields=common_fields, validator=ExtraFieldsSchema())

    def call(self, objs):
        gtopics = model.FinalWorkTopic.select()
        came_from = cherrypy.request.headerMap['Referer']

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(DictionaryField(
                name="mt_%d" % sig.id,
                model_object_name='MarkType',
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putmark'),
            submit_text=_("Put marks"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_mark",
            form=form,
            topics=gtopics,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @expose()
    def index(self):
        raise redirect(".")

    @expose()
    @validate(form=common_form)
    @error_handler(index)
    def putmark(self, obj, came_from,
                group_topic_id, can_replace=False, protocol_number='', comment='', **kw):
        # Extract args
        group_topic = model.FinalWorkTopic.get(int(group_topic_id))
        owner = identity.current.user.person

        mark_types = []
        for k, v in kw.iteritems():
            if not v:
                continue

            assert k[:3] == 'mt_'
            id = int(k[3:])
            mark_types.append((model.StudentInGroup.get(id), model.MarkType.get(int(v))))

        # Put marks
        exceptions = []
        for sig, mt in mark_types:
            marks = model.FinalWorkMark.selectBy(topic=group_topic, student=sig.student)
            if marks.count() > 0:
                mark = list(marks)[0]

                if mark.protocolNumber is None or protocol_number is not None:
                    mark.protocolNumber = protocol_number

                if mark.markType == mt:
                    if mark.comment != comment:
                        mark.comment = comment
                    continue

                if can_replace:
                    mark.markType = mt
                else:
                    exceptions.append((sig.title,
                        _("Mark '%s' was put already") % mark.markType.title))
            else:

                hours = Decimal(0)
                topic_hours = [gt.hours for gt in sig.group.gtopics if gt.topic == group_topic.topic]
                if len(topic_hours):
                    hours = topic_hours[0]

                if protocol_number is None:
                    protocol_number = u''

                model.FinalWorkMark(
                    owner=owner,
                    topic=group_topic,
                    student=sig.student,
                    hours=hours,
                    markType=mt,
                    protocolNumber=protocol_number,
                    comment=comment)

        if len(exceptions) > 0:
            raise ExceptionsBunch(exceptions)

        raise redirect(came_from)

class MAPutFinalMarkForTeacher(MAPutFinalMark):
    name = "put_final_mark_for_teacher"
    title = _("Put final mark for teacher")

    common_fields = [
        DictionaryField(name='group_topic_id',
            model_object_name='FinalWorkTopic', not_empty=True, label=_("Topic")),
        widgets.CheckBox(name='can_replace',
            default=False, label=_("Replace values?")),
        widgets.TextField(name="protocol_number", not_empty=False, label=_("Protocol #")),
        column_widget(model.Mark.sqlmeta.columns.get('comment')),
        widgets.HiddenField(name='came_from')
    ]

    common_form = widgets.TableForm(fields=common_fields, validator=ExtraFieldsSchema())

    def call(self, objs):
        gtopics = set()
        for sig in objs:
            gtopics = gtopics.union(set(sig.group.gtopics))

        topics = [gt.topic for gt in gtopics]

        final_work_topics = set()
        for t in topics:
            final_work_topics = final_work_topics.union(model.FinalWorkTopic.selectBy(topic=t))

        came_from = cherrypy.request.headerMap['Referer']

        if not ifReferFromGroup(came_from):
            turbogears.flash(_('This mass action works only from group page.'))
            raise turbogears.redirect(came_from)

        number = getGroupFromRefer(came_from)
        user = turbogears.identity.current.user

        if not getGroups(user).count(number):
            turbogears.flash(_('It not your group.'))
            raise turbogears.redirect(came_from)

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(DictionaryField(
                name="mt_%d" % sig.id,
                model_object_name='MarkType',
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putmark'),
            submit_text=_("Put marks"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_mark",
            form=form,
            topics=final_work_topics,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    @validate(form=common_form)
    @expose()
    def putmark(self, obj, came_from,
                group_topic_id, can_replace=False, protocol_number='', comment='', **kw):
        MAPutFinalMark.putmark(self, obj, came_from,
                               group_topic_id, can_replace, protocol_number, comment, **kw)

class MAPutMark(MassAction):
    target_class = model.StudentInGroup
    name = "putmark"
    title = _("Put mark")

    common_fields = [
        PlanTopicField(name="group_topic_id", not_empty=True, label=_("Topic")),
        widgets.CheckBox(name='can_replace',
            default=False, label=_("Replace values?")),
        column_widget(model.Mark.sqlmeta.columns.get('comment')),
        widgets.HiddenField(name='came_from')
    ]

    common_form = widgets.TableForm(fields=common_fields, validator=ExtraFieldsSchema())

    def call(self, objs):
        gtopics = model.Topic.select()
        came_from = cherrypy.request.headerMap['Referer']

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(DictionaryField(
                name="mt_%d" % sig.id,
                model_object_name='MarkType',
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putmark'),
            submit_text=_("Put marks"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_mark",
            form=form,
            topics=gtopics,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    @validate(form=common_form)
    @expose()
    def putmark(self, obj, came_from, group_topic_id, can_replace=False, comment='', **kw):
        # Extract args
        group_topic = model.PlanTopic.get(int(group_topic_id))
        owner = identity.current.user.person

        mark_types = []
        for k, v in kw.iteritems():
            if not v:
                continue

            assert k[:3] == 'mt_'
            id = int(k[3:])
            mark_types.append((model.StudentInGroup.get(id), model.MarkType.get(int(v))))

        # Put marks
        exceptions = []
        for sig, mt in mark_types:
            marks = model.Mark.selectBy(topic=group_topic.topic, student=sig.student)
            if marks.count() > 0:
                mark = list(marks)[0]
                if mark.markType == mt:
                    if mark.comment != comment:
                        mark.comment = comment
                    continue

                if can_replace:
                    mark.markType = mt
                else:
                    exceptions.append((sig.title,
                        _("Mark '%s' was put already") % mark.markType.title))
            else:
                model.Mark(owner=owner, topic=group_topic.topic, student=sig.student,
                    hours=group_topic.hours, markType=mt, comment=comment)

        if len(exceptions) > 0:
            raise ExceptionsBunch(exceptions)

        raise redirect(came_from)

class MAPutMarkForTeacher(MAPutMark):
    name = "putmark_for_teacher"
    title = _("Put mark for teacher")

    common_fields = [
        DictionaryField(name='group_topic_id',
            model_object_name='GroupTopic', not_empty=True, label=_("Topic")),
        widgets.CheckBox(name='can_replace',
            default=False, label=_("Replace values?")),
        column_widget(model.Mark.sqlmeta.columns.get('comment')),
        widgets.HiddenField(name='came_from')
    ]

    common_form = widgets.TableForm(fields=common_fields, validator=ExtraFieldsSchema())

    def call(self, objs):
        gtopics = set()
        for sig in objs:
            gtopics = gtopics.union(set([gt for gt in sig.group.gtopics if gt.topic.isFinalWork == False]))

        came_from = cherrypy.request.headerMap['Referer']

        if not ifReferFromGroup(came_from):
            turbogears.flash(_('This mass action works only from group page.'))
            raise turbogears.redirect(came_from)

        number = getGroupFromRefer(came_from)
        user = turbogears.identity.current.user

        if not getGroups(user).count(number):
            turbogears.flash(_('It not your group.'))
            raise turbogears.redirect(came_from)

        fields = self.common_fields[:]
        for sig in objs:
            fields.append(DictionaryField(
                name="mt_%d" % sig.id,
                model_object_name='MarkType',
                label=sig.student.title
            ))

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('putmark'),
            submit_text=_("Put marks"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.put_mark",
            form=form,
            topics=gtopics,
            came_from=came_from,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    @validate(form=common_form)
    @expose()
    def putmark(self, obj, came_from, group_topic_id, can_replace=False, comment='', **kw):
        # Extract args
        group_topic = model.GroupTopic.get(int(group_topic_id))
        owner = identity.current.user.person

        mark_types = []
        for k, v in kw.iteritems():
            if not v:
                continue

            assert k[:3] == 'mt_'
            id = int(k[3:])
            mark_types.append((model.StudentInGroup.get(id), model.MarkType.get(int(v))))

        # Put marks
        exceptions = []
        for sig, mt in mark_types:
            marks = model.Mark.selectBy(topic=group_topic.topic, student=sig.student)
            if marks.count() > 0:
                mark = list(marks)[0]
                if mark.markType == mt:
                    if mark.comment != comment:
                        mark.comment = comment
                    continue

                if can_replace:
                    mark.markType = mt
                else:
                    exceptions.append((sig.title,
                        _("Mark '%s' was put already") % mark.markType.title))
            else:
                model.Mark(owner=owner, topic=group_topic.topic, student=sig.student,
                    hours=group_topic.hours, markType=mt, comment=comment)

        if len(exceptions) > 0:
            raise ExceptionsBunch(exceptions)

        raise redirect(came_from)

class MAOplataDocument(MassAction):
    target_class = model.StudentInGroup
    name = "oplata_document"
    title = _("Oplata document")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )
    read_only = True

    def call(self, objs, month, year):
        return Report.generate('Oplata',
            ids=objs2ids(objs),
            charge_year=year,
            charge_month=month,
        )

class MARealhours(MassAction):
    target_class = model.StudentInGroup
    name = "realhours"
    title = _("Change real hours")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )

    def call(self, objs, month, year):
        exceptions = []
        records = []
        for sig in objs:
            crs = list(model.ChargeRecord.selectBy(
                billingMonth=month, billingYear=year,
                student=sig.student, studentAgreement=sig.studentAgreement
            ))
            if len(crs) != 1:
                exceptions.append((sig.title,
                    _("Payment wasn't charged for %02d.%04d") % (month, year)))
            else:
                records.append(crs[0])
        if len(exceptions) > 0:
            raise ExceptionsBunch(exceptions)
        came_from = cherrypy.request.headerMap['Referer']
        return dict(
            tg_template="genshi:mnemoply.templates.realhours",
            records=records,
            came_from=came_from,
            action=self.getURL('realhours')
        )

    @expose()
    def realhours(self, obj, came_from, **kw):
        for k, v in kw.iteritems():
            if k.startswith('rh_'):
                id = int(k[3:])
                cr = model.ChargeRecord.get(id)
                v = v.replace(",", ".")  # Users enter v as "12,2" with comma as separator
                cr.realHours = v         # But we need decimal value with dot as separator like "12.2"

        raise redirect(came_from)

class MACouponApply(MassAction):
    target_class = model.StudentInGroup
    name = "coupon_apply"
    title = _("Apply coupon")

    form = MassActionForm(
        name=name,
        fields=[]
        )

    common_fields = [
        widgets.HiddenField(name='came_from'),
        ]

    common_form = widgets.TableForm(fields=common_fields)

    def call(self, objs):
        came_from = cherrypy.request.headerMap['Referer']
        fields = self.common_fields[:]
        for sig in objs:
            fields.append(
                    CouponActiveField(name="coupon_%d" % sig.id,
                                 label=sig.title))

        form = widgets.TableForm(fields=fields,
                                 action=self.getURL('apply'),
                                 submit_text=_("Apply coupon"))

        return dict(tg_template="genshi:mnemoply.templates.coupon_apply",
                    form=form,
                    came_from=came_from,
                    ids=objs2ids(objs))

    @validate(form=common_form)
    @expose()
    def apply(self, obj, came_from, **kw):
        for k, v in kw.iteritems():
            if not v:
                continue
            id = k[7:]
            coupon = model.Coupon.get(v['hidden'])
            studentInGroup = model.StudentInGroup.get(id)
            agreement = studentInGroup.studentAgreement
            self.successfully_execute = coupon.Apply(agreement) #not work? need fix
        raise redirect(came_from)


class MAPay(MassAction):
    target_class = model.StudentInGroup
    name = "pay"
    title = _("Enter payment")

    def call(self, sigs):
        came_from = cherrypy.request.headerMap['Referer']
        registers = model.CashRegister.select()
        return dict(
            sigs=sigs,
            all_registers=registers,
            tg_template="genshi:mnemoply.templates.payment",
            came_from=came_from,
            action=self.getURL('pay_confirm'),
        )

    def extract_amount_values(self, kw):
        what = []
        not_empty_number = validators.Number(not_empty=True)
        for k, v in kw.iteritems():
            if k.startswith('amount_'):
                id = int(k[7:])
                if not len(v.strip()):
                    continue
                amount = not_empty_number.to_python(v)
                comment = kw['comment_' + str(id)]
                register_id = kw['register']
                # return first item from list, is it's list
                if isinstance(register_id, list):
                    register_id = register_id[0]
                register = model.CashRegister.get(id=int(register_id))

                start_date_str = kw['start_date']
                # return first item from list, is it's list
                if isinstance(start_date_str, list):
                    start_date_str = start_date_str[0]
                start_date = str2date2(start_date_str)

                what.append((model.StudentInGroup.get(id), amount, register, start_date, comment))
        return what

    @expose()
    def pay_confirm(self, obj, came_from, **kw):
        what = self.extract_amount_values(kw)
        return dict(
            tg_template="genshi:mnemoply.templates.payment_confirm",
            what=what,
            action=self.getURL('pay'),
            came_from=came_from,
        )

    @expose()
    def pay(self, obj, came_from, **kw):
        what = self.extract_amount_values(kw)

        for sig, amount, register, date, comment in what:
            model.PaymentRecord(
                student=sig.student,
                studentAgreement=sig.studentAgreement,
                amount=amount,
                comment=comment,
                register=register,
                date=date,
            )

        raise redirect(came_from)

class MigrationWidget(widgets.Widget):
    name = "migration_widget"
    headers = [_("Student"), _("Current school form"), _("Average mark"), _("Initial plan teacher wish"),
               _("Opponents"),
               _("Behaviour comment"),
               _("Comment"),
               _("Health problems")]
    rows = []

    validator = None

    def __init__(self, sigs, plan, *args, **kw):
        super(MigrationWidget, self).__init__(*args, **kw)

        self.rows = []
        for sig in sigs:
            self.rows.append(self.getRow(sig, plan))

    def getRow(self, sig, plan):
        return [
            Span(value=sig.student.title),
            Span(value=sig.student.schoolForm),
            column_avg_mark(model.StudentMigration.sqlmeta.columns.get("avgMark"), "avgmark_" + str(sig.id)),
            DictionaryField(
                name="planid_" + str(sig.id),
                model_object_name='Plan',
                not_empty=True,
                sort_func=[planSortFunction],
                records=lambda: [pt.nextPlan for pt in model.PlanTransfer.selectBy(currentPlan=plan)],
                attrs={'style':"width:150px;"}
            ),
            widgets.TextField(name="opponents_" + str(sig.id), attrs={'size': 18}),
            widgets.TextField(name="behavcomment_" + str(sig.id), attrs={'size': 18}),
            widgets.TextField(name="comment_" + str(sig.id), attrs={'size': 18}),
            widgets.TextField(name="healthproblem_" + str(sig.id), attrs={'size': 18}),
        ]

class MAMigrationCreate(MassAction):
    target_class = model.StudentInGroup
    name = "migration_create"
    title = _("Create migration")

    def call(self, objs):

        came_from = cherrypy.request.headerMap['Referer']

        if not ifReferFromGroup(came_from):
            turbogears.flash(_('This mass action works only from group page.'))
            raise turbogears.redirect(came_from)

        number = getGroupFromRefer(came_from)
        user = turbogears.identity.current.user

        if not getGroups(user).count(number):
            turbogears.flash(_('It not your group.'))
            raise turbogears.redirect(came_from)

        current_plan = objs[0].group.initialPlan
        teacher = user.person

        fields = [GridField(MigrationWidget(sigs=objs, plan=current_plan)),
            widgets.HiddenField(name='came_from'),
            widgets.HiddenField(name='current_plan'),
            widgets.HiddenField(name='teacher'),
            ]

        form = widgets.TableForm(
            fields=fields,
            action=self.getURL('create_migrations'),
            submit_text=_("Create migrations"),
        )

        return dict(
            tg_template="genshi:mnemoply.templates.create_migration",
            form=form,
            came_from=came_from,
            current_plan=current_plan.id,
            teacher=teacher.id,
            ids=objs2ids(objs),
        )

    @handle_std_exceptions()
    #@validate(form=common_form)
    @expose()
    def create_migrations(self, obj, came_from, current_plan, teacher, **kw):
        current_plan = model.Plan.get(int(current_plan))
        teacher = model.Person.get(int(teacher))

        dict = {}

        for k, v in kw['widget'].iteritems():
            key, id = k.split("_")
            id = int(id)
            if id not in dict:
                dict[id] = {}
            dict[id][key] = v

        for k, v in dict.iteritems():
            if 'planid' in v and isint(v['planid']):
                sig = model.StudentInGroup.get(k)
                teacher_plan = model.Plan.get(int(v['planid']))
                avgmark = v['avgmark']
                comment = v['comment']
                healthproblem = v['healthproblem']
                behavcomment = v['behavcomment']
                opponents = v['opponents']

                model.StudentMigration(
                    student=sig.student,
                    groupFrom=sig.group,
                    opponents=opponents,
                    initialPlanTeacherWish=teacher_plan,
                    avgMark=avgmark,
                    healthProblems=healthproblem,
                    behaviourComment=behavcomment,
                    teacher=teacher,
                    plan=current_plan,
                    comment=comment
                )
            else:
                pass  # TODO return ExceptionsBunch

        raise turbogears.redirect(came_from)

class MACreateTemporaryPaymentRecords(MassAction):
    target_class = model.StudentInGroup
    name = "create_temporary_payment_records"
    title = _("Create temporary payment records")

    def call(self, objs):
        information_source = model.InformationSource.byStringId('our_student')
        for sig in objs:
            model.TemporaryPaymentRecord(
                student=sig.student,
                organization=sig.group.organization,
                trend=sig.group.initialPlan.trend,
                tempSurname=sig.student.surname,
                tempForename=sig.student.forename,
                tempPatronymic=sig.student.patronymic,
                informationSource=information_source,
                phone=sig.studentAgreement.customer.phone,
                register=None,
            )

class MACreateContractAndPrintAgreement(MassAction):
    target_class = model.StudentInGroup
    name = "create_contract_and_print_agreement"
    title = _("Agreement print")
    read_only = True
    form = MassActionForm(name=name,
        fields=[
            widgets.CheckBox(name="print_copy", label=_("Print copy")),
        ]
        )

    def call(self, objs,print_copy):
        lst = []
        for obj in objs:
            agr = StudentAgreement.get(obj.studentAgreementID)
            find=Contract.selectBy(organization=agr.organization,
                                       student = agr.student,
                                       customer = agr.customer)
            if find.count() > 0:
                contract = list(find)[0]
            else:
                contract = Contract(organization=agr.organization,
                                       student = agr.student,
                                       customer = agr.customer)
            agr.contract = contract
            find=StudentAgreement.selectBy(organization=agr.organization,
                                       student = agr.student,
                                       customer = agr.customer,
                                       dateCancellationAgreement = None)
            
            if find.count() > 0:
                agrms = list(find)
            no_ord = [a for a in agrms if a.ordinal==0]
            beg = len(agrms) - len(no_ord)+1
            for i,a in enumerate(no_ord):
                a.ordinal = beg+i
            for a in agrms:
                a.contract = contract
                if  (print_copy or not a.countPrint) and a.organization.id == 11:
                    lst.append(a)
                    a.countPrint = a.countPrint + 1
        self.successfully_execute = (len(lst) ==len(objs))
        if not lst:
            return 
 
        return Report.generate('ContractAgreementPrint',
            ids=objs2ids(lst),
        )

class MACreateContractAndPrint(MassAction):
    target_class = model.StudentInGroup
    name = "create_contract_and_print"
    title = _("Contract print")
    read_only = True
    form = MassActionForm(name=name,
        fields=[
            widgets.CheckBox(name="print_copy", label=_("Print copy")),
        ]
        )

    def call(self, objs,print_copy):
        cns = []
        for obj in objs:
            agr = StudentAgreement.get(obj.studentAgreementID)
            find=Contract.selectBy(organization=agr.organization,
                                       student = agr.student,
                                       customer = agr.customer)
            if find.count() > 0:
                contract = list(find)[0]
            else:
                contract = Contract(organization=agr.organization,
                                       student = agr.student,
                                       customer = agr.customer)
            if  (print_copy or not contract.countPrint) and agr.organization.id == 11: 
                cns.append(contract)
                contract.countPrint = contract.countPrint + 1
        self.successfully_execute = (len(cns) ==len(objs))
        if not cns :
            return 
 
        return Report.generate('ContractPrint',
            ids=objs2ids(cns),
        )



class StudentInGroupDataSource(TableLookupDataSource):
    """
        Provides `group_lookup` with filtration by `is_open`.
    """

    def __init__(self):
        TableLookupDataSource.__init__(self, 'student_in_group_lookup')

    def _buildWhereChunks(self, request):
        chunks = TableLookupDataSource._buildWhereChunks(self, request)
        chunks.append(self.buildChunksOr("office", AuthUserOffice))
        chunks.append(self.buildChunksOr("faculty", AuthUserFaculty))
        chunks.append(self.buildChunksOr("organization", AuthUserOrg))
        return chunks
class StudentInGroupController(LookupController, ModelObjectContainer):
    lookup_columns = [
        TableCol(name='faculty', caption=_("Faculty"), size=3),
        TableCol(name='ed_group', caption=_("Group")),
        TableCol(name='student', caption=_("Student")),
        TableCol(name='school_form', caption=_("School form"), size=3),
        TableCol(name='teacher', caption=_("Teacher")),
        TableCol(name='cache_balance', caption=_("Balance")),
        TableCol(name='office_str', caption=_("Office"), hidden=True),
        TableCol(name='group_days', caption=_("Schedule days"), hidden=True),
        TableCol(name='last_year_group', caption=_("Last year group"), hidden=True),
    ]
    model_object = model.StudentInGroup

    change_discont_form = widgets.TableForm(
        fields=[
            DiscontField(
                name="discont",
                not_empty=True,
                label='',
            ),
        ],
        submit_text=_("Change disconts"),
        action="change_discont",
    )

    @identity.require(identity.has_any_permission('dba', 'StudentInGroup/edit'))
    @validate(form=change_discont_form)
    @expose()
    def change_discont(self, obj, discont, tg_errors=None):
        if tg_errors:
            return self.show(obj)
        obj.discont = discont
        raise redirect("./")
    change_discont.expose_object = True

    @expose(template="genshi:mnemoply.templates.sig_show")
    def show(self, obj):
        return dict(
            change_discont_form=self.change_discont_form,
            obj=obj,
        )
    show.expose_object = True

    def __init__(self):
        LookupController.__init__(self,
            data_source=StudentInGroupDataSource(),
            columns=self.lookup_columns,
            mass_actions_class=self.model_object,
            title=self.model_object.model_title,
            default_order_by='student',
        )
        ModelObjectContainer.__init__(self, model_object=self.model_object)

    def fill_lookup_data_defaults(self, data):
        is_parent_filled = LookupController.fill_lookup_data_defaults(self, data)
        if not is_parent_filled:
            office = identity.current.user.office.name
            args = {'flt_office_str': office, 'column': ['student', 'ed_group', 'teacher', 'office_str']}
            data.update(args)

exposed = StudentInGroupController()
